// ==UserScript==
// @name        YE功能增强.00 - [Utils工具类集合]
// @description Utils 工具类
// @namespace   http://AsionTang.CN
// @copyright   2017+, AsionTang
// @author      AsionTang
// @version     240618.11.06.017
// @run-at      document-start
// @downloadURL https://gitee.com/AsionTang/52.ScriptLibrary/raw/master/YeJS/00.Utils.js
// @grant       none
// ==/UserScript==
// @Formatter   TypeScript and JavaScript Language Features

/**
 * 任意对象 转换 为时间字符串.
 */
function obj2DateTime(str) {
    if (!str)
        return undefined;

    str = ('' + str).trim();
    //
    //替换特殊空格如:2018年01月10日 18:15:54里的空格其实是encodeURIComponent(str.charAt(11))=%C2%A0 中文的说法是这货&nbsp
    //php - 请问这是什么字符“'%C2%A0'”？ - SegmentFault https://segmentfault.com/q/1010000002754028
    str = str.replace(/\s+/gm, ' ');
    //补充年份：5月2号>2017年5月2号
    str = str.replace(/^(\d{1,2})月/gm, new Date().getFullYear() + '年$1月');
    str = str.replace(/^(\d{1,2})年/gm, '20$1年');
    str = str.replace(/^(\d{1,2})[^\d :](\d{1,2})[^\d :](\d{1,2})[日|号]*/gm, '20$1-$2-$3');
    //补充年份：171024 160012
    str = str.replace(/^(\d{6}) /gm, '20$1 ');
    //补充年份：1024 160012
    str = str.replace(/^(\d{4}) /gm, new Date().getFullYear() + '$1 ');
    //月份补0：
    str = str.replace(/年(\d)月/gm, '年0$1月');
    //日补0：
    str = str.replace(/月(\d)[日|号]/gm, '月0$1日');
    //替换分隔符：2017/1/1>2017-01-1
    str = str.replace(/\//gm, '-');
    //月份补0：2017-1-1>2017-01-1
    str = str.replace(/-(\d)-/gm, '-0$1-');
    //日补0：2017-1-1>2017-1-01
    str = str.replace(/-(\d)$/gm, '-0$1');
    //日补0：2017-1-1 >2017-1-01
    str = str.replace(/-(\d) /gm, '-0$1 ');
    //时补0：9:1> 09:1
    str = str.replace(/ (\d):/gm, ' 0$1:');
    //分补0：9:1> 9:01 |9:1:1>9:1:01
    str = str.replace(/:(\d)$/gm, ':0$1');
    //分补0：9:1:1> 9:01:1
    str = str.replace(/:(\d):/gm, ':0$1:');
    //秒补0：9:1:1> 9:01:1
    str = str.replace(/:(\d):/gm, ':0$1:');
    //移除除了 空格 之外的字符：20170104 090101
    str = str.replace(/[^ \d]/gm, '');
    //20170104
    if (str.length == 8)
        str = str + ' 000000';
    //0617 232124>20240617 232124
    if (str.length == 11)
        str = new Date().getFullYear() + str;
    //20170104 0901
    if (str.length == 13)
        str = str + '00';
    //20170104 090100
    if (str.length != 15)
        return undefined;
    str = str.replace(/^(\d{4})(\d{2})(\d{2}) (\d{2})(\d{2})(\d{2})$/gm, '$1.$2.$3 $4:$5:$6');
    if (new Date(str).toString() == "Invalid Date")
        return undefined;
    return str;
}

/**
 * 自动四舍五入指定位数，并去掉末尾的0占位符
 */
function toFixedEx(number, fixedCount) {
    return number.toFixed(fixedCount).replace(/(\.?[0]+$)/g, '');
}

/**
 * 去除产品名称常见的非必要字符
 */
function toPureName(name) {
    name = name.replace(/【[^【】]+】/gm, '');
    name = name.replace(/\([^\(\)]+\)/gm, '');
    name = name.replace(/（[^（）]+）/gm, '');
    name = name.replace(/\t/gm, ' ');
    name = name.replace(/\n/gm, ' ');
    name = name.replace(/ +/gm, ' ');
    name = name.replace(/^ /gm, '');
    name = name.replace(/ $/gm, '');
    return name;
}

/**
 * 获取干净的日期时间字符串
 */
function toPureDateTime(time) {
    //实际使用过程中发现有好多时间换行了,导致获取到的时间字符串不正确了.所以需要将其替换为空格
    //\s is a shorthand for [ \t\r\n\f], whereas \S equivals to [^ \t\r\n\f]
    time = time.replace(/\s+/gm, ' ');
    time = time.replace(/[^\d\- :]/gm, '');
    return time.trim();
}

/**
 * 提取出字符串里的数字
 * @return {Number} 转换为数字失败时返回0.
 */
function toNumber(str) {
    if (!str || !str.replace)
        return 0;
    return Number(('' + str).replace(/[^\d\.\-]/g, ''));
}

/**
 * 通过正则表达式返回 【匹配的字符串】,然后将字符串里的非数字的字符移除掉后,返回对应的数字
 * 例如: 淘金币:-$1.20元 转换后 返回-1.20 有负号.
 * @param {RegExp} regEx 无需在正则表达式里带上()捕获组字符
 * @param {string} text 
 * @return {Number} 转换为数字失败时返回0.
 */
function getNumber(regEx, text) {
    var values = text.match(regEx);
    if (!values || values.length != 1) {
        console.error('正则表达式匹配错误:' + '\n正则表达式:' + regEx + '\n待匹配文本:' + text);
        return 0;
    }
    return toNumber(values[0]);
}

/**
 * 通过正则表达式返回 【第一个捕获组()】里的文本,对应的 去掉非数字字符后的 数字
 * 例如: 淘金币:-$1.20元 /淘金币抵扣：\-￥(\d+\.\d+)/g 匹配后 返回1.20 没有负号.
 * @param {RegExp} regEx 
 * @param {string} text 
 * @return {Number} 转换为数字失败时返回0.
 */
function getNumberEx(regEx, text) {
    let x = text.matchAll(regEx).next();
    if (!x || !x.value) {
        console.error('正则表达式匹配错误:' + '\n正则表达式:' + regEx + '\n待匹配文本:' + text);
        return 0;
    }
    if (x.value.length != 2) {
        console.error('正则表达式，捕获组数量有误:' + '\n正则表达式:' + regEx + '\n待匹配文本:' + text + '\n实际捕获组数量:' + x.value.length + '实际捕获组详情:' + JSON.stringify(x.value));
        return 0;
    }
    return toNumber(x.value[1]);
}

/**
 * 一直向上获取指定Tag标签的父节点
 */
function getParentElementByTagName(e, tagName) {
    if (e.tagName.toUpperCase() == tagName.toUpperCase())
        return e;
    if (e.parentElement == null)
        return null;
    return getParentElementByTagName(e.parentElement, tagName);
}

/**
 * 在标题栏显示一定的Toast信息,指定时间后恢复原来的标题. 同时记录错误到Console
 */
function showToastAtTitleAndLogError(error) {
    showToastAtTitle(error);
    console.error(error);
}

/**
 * 在标题栏显示一定的Toast信息,指定时间后恢复原来的标题.
 */
function showToastAtTitle(info) {
    if (!document.Ye_OldTitle)
        document.Ye_OldTitle = document.title;
    document.title = info;
    clearTimeout(document.Ye_showToastAtTitle_setTimeoutId);
    document.Ye_showToastAtTitle_setTimeoutId = setTimeout(function () {
        document.title = document.Ye_OldTitle;
        document.Ye_OldTitle = null;
    }, 1000);
}

/**
 * 检测当前网址是否匹配
 */
function isLocationHrefMatch(regStr) {
    return new RegExp(regStr.replace(/\*/g, '.*'), 'gi').test(location.href);
}

/**
 * 检测当前网址是否匹配
 */
function isLocationHrefContainsAll() /*needCheckContainsArray*/ {
    //通过arguments来拿到不定长度的参数列表.实现类似变参的效果.
    for (var i = 0; i < arguments.length; i++)
        if (location.href.indexOf(arguments[i]) == -1)
            return false;
    return true;
}

/**
 * 通用注入原型4：支持直接将URL注入到原网页
 */
function inject(funcOrUrl) {
    var YETAG;
    YETAG = document.createElement('script');
    YETAG.type = 'text/javascript';
    YETAG.id = 'YEJS_' + +new Date();
    if (typeof (funcOrUrl) == 'function') {
        var YEJS = "";
        YEJS += "//================== [YEJS START] =======================";
        YEJS += "\n(";
        YEJS += funcOrUrl;
        YEJS += ")();\n";
        YEJS += "//================== [YEJS ENDED] =======================";
        YETAG.innerHTML = YEJS;
    } else
        YETAG.src = funcOrUrl;
    document.body.appendChild(YETAG);
}